package com.yfunc.common.persistence.ibatis;

import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import com.yfunc.common.persistence.ibatis.CommandType.Type;

@Intercepts({ 
	@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class }) ,
	@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class  , RowBounds.class , ResultHandler.class }) 
})
public class CommandInterceptor implements Interceptor {

	private HandlerFactory factory;

	public CommandInterceptor() {
		this.factory = new HandlerFactory();
	}

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		Object[] args = invocation.getArgs();
		Type commandType = CommandType.getType(((MappedStatement) args[0]).getId());
		if (commandType != null) {
			for (Handler handler : factory.getHandlers()) {
				if (handler.isSupported(commandType)) {
					Command command = getCommandParameter(args);
					command = handler.execute(command, commandType);
					setParameterArgs(args, command);
				}
			}
		}
		return invocation.proceed();
	}

	private Command getCommandParameter(Object[] args) {
		MappedStatement mapperStatement = (MappedStatement) args[0];
		Object parameter = args[1];
		return new Command(mapperStatement, parameter);
	}

	private void setParameterArgs(Object[] args, Command command) {
		args[0] = command.getMappedStatement();
		args[1] = command.getParameter();
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
	}
}
